package fr.inserm.umr915.vcfannotator;

import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.je.DatabaseEntry;

/**
 * 
 * Variant
 *
 */
public class Variant
	implements Comparable<Variant>
	{
	private String build;
	private String chrom;
	private int position;
	private String ref;
	private String alt;
	
	public Variant(
			String build,
			String chrom,
			int position,
			String ref,
			String alt
			)
		{
		this.build = build;
		this.chrom = chrom;
		this.position = position;
		this.ref = ref;
		this.alt = alt;
		}
	private Variant()
		{
		}

	public String getBuild()
		{
		return build;
		}

	public String getChrom()
		{
		return chrom;
		}

	public int getPosition()
		{
		return position;
		}

	public String getRef()
		{
		return ref;
		}

	public String getAlt()
		{
		return alt;
		}

	@Override
	public int hashCode()
		{
		final int prime = 31;
		int result = 1;
		result = prime * result + alt.hashCode();
		result = prime * result + build.hashCode();
		result = prime * result + chrom.hashCode();
		result = prime * result + position;
		result = prime * result + ref.hashCode();
		return result;
		}

	@Override
	public boolean equals(Object obj)
		{
		if (this == obj) { return true; }
		if (obj == null) { return false; }
		if (getClass() != obj.getClass()) { return false; }
		Variant other = (Variant) obj;
		if (!alt.equals(other.alt)) { return false; }
		if (!build.equals(other.build)) { return false; }
		if (!chrom.equals(other.chrom)) { return false; }
		if (position != other.position) { return false; }
		if (!ref.equals(other.ref)) { return false; }
		return true;
		}

	@Override
	public String toString()
		{
		return "(" + build + ")" + chrom + ":"
				+ position + " " + ref + "/" + alt;
		}
	
	@Override
	public int compareTo(Variant o)
		{
		if(o==this) return 0;
		if(o==null) return -1;
		int i= getBuild().compareTo(o.getBuild());
		if(i!=0) return i;
		i= getChrom().compareTo(o.getChrom());
		if(i!=0) return i;
		i= getPosition()-o.getPosition();
		if(i!=0) return i;
		i= getRef().compareTo(o.getRef());
		if(i!=0) return i;
		i= getAlt().compareTo(o.getAlt());
		return i; 
		}
	public static class Sorter
		implements Comparator<byte[]>
		{
		@Override
		public int compare(byte[] o1, byte[] o2)
			{
			Binding bind=new Binding();
			Variant v1= bind.entryToObject(new DatabaseEntry(o1));
			Variant v2= bind.entryToObject(new DatabaseEntry(o2));
			return v1.compareTo(v2);
			}
		}
	
	public static class Binding
		extends TupleBinding<Variant>
		{
		@Override
		public Variant entryToObject(TupleInput in)
			{
			Variant v=new Variant();
			v.build=in.readString();
			v.chrom=in.readString();
			v.position=in.readInt();
			v.ref=in.readString();
			v.alt=in.readString();
			return v;
			}
		@Override
		public void objectToEntry(Variant v, TupleOutput out)
			{
			out.writeString(v.getBuild());
			out.writeString(v.getChrom());
			out.writeInt(v.getPosition());
			out.writeString(v.getRef());
			out.writeString(v.getAlt());
			}
		}
	public static Set<String> alts(String ref,String alt)
		{
		Set<String> set=new HashSet<String>();
		ref=ref.toUpperCase();
		alt=alt.toUpperCase();
		int i=alt.indexOf(',');
		if(i!=-1)
			{
			set.addAll(alts(ref,alt.substring(0,i)));
			set.addAll(alts(ref,alt.substring(i+1)));
			return set;
			}
		 if(alt.equals("N"))
			 {
			 set.add("A");
			 set.add("T");
		     set.add("G");
		     set.add("C");
			 }
		 else if(alt.equals("W")) { set.add("A");set.add("T");}
		 else if(alt.equals("S")) { set.add("G");set.add("C");}
		 else if(alt.equals("B")) { set.add("T");set.add("G");set.add("C");}
		 else if(alt.equals("D")) { set.add("A");set.add("T");set.add("G");}
		 else if(alt.equals("H")) { set.add("A");set.add("T");set.add("C");}
		 else if(alt.equals("V")) { set.add("A");set.add("G");set.add("C");}
		 else if(alt.equals("K")) { set.add("G");set.add("T");}
		 else if(alt.equals("M")) { set.add("A");set.add("C");}
		 else if(alt.equals("R")) { set.add("A");set.add("G");}
		 else if(alt.equals("Y")) { set.add("C");set.add("T");}
		 else
		 	{
			set.add(alt); 
		 	}
		set.remove(ref);
		set.remove("");
		return set;
		}
	}
